package br.eng.eliseu.gwt.gestaoWeb.server.atualizacao;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.Callable;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.hibernate.HibernateException;

import br.eng.eliseu.gwt.gestaoWeb.model.nucleo.TabelaPadrao;
import br.eng.eliseu.gwt.gestaoWeb.server.util.ConnectionUtil;
import br.eng.eliseu.gwt.gestaoWeb.server.util.UpperCaseFileNameFilter;

public class UpgradeTabelasPadraoCommand implements Callable<Void> {

//	 @Inject
//	 Provider<EntityManager> entityManager;
//	 private EntityManager em = entityManager.get();

	private String path;
	private String arquivoConfigXML;

	// private List<ErroAtualizacao> erros = new ArrayList<ErroAtualizacao>();

	private Connection connection;

	public Void call() throws Exception {
		try {
			connection = ConnectionUtil.getInstance().getConnection();

			try {
				/*
				 * Compara o arquivo CADTP.xml com a tabela TabelaPadrao do banco e retorna uma lista com as tabelas 
				 * que devem ser atualizadas
				 */
				VerificaTabelasPadrao vtp = new VerificaTabelasPadrao();
				List<TabelaPadrao> listaXMLHaAtualizar = vtp.getListaTabelasHaAtualizar(connection, getPath(), getArquivoConfigXML());

				/*
				 * Procuro na pasta os arquivos que estao descritos no XML
				 */
				File diretorioTemporario = new File(getPath());
				for (TabelaPadrao tp : listaXMLHaAtualizar) {
					File[] arquivos = diretorioTemporario.listFiles(new UpperCaseFileNameFilter(tp.getNomeArquivo()));
					if (arquivos != null && arquivos.length > 0) {
						// --- Encontrou o arquivo
						File file = arquivos[0];
						atualizaTabelaPadrao(file, tp);
					}
				}
			} catch (Exception e) {
				throw new Exception(e);
			}
		} catch (Exception e) {
		}
		return null;
	}

	
	private void setForeignKeyConstraintsCheck(boolean state) {
        final byte sqlState = (byte) (state ? 1 : 0);
        try {
        	connection.createStatement().execute("SET FOREIGN_KEY_CHECKS = " + sqlState);
        } catch (HibernateException e) {
        	System.out.println(e.getMessage());
        } catch (SQLException e) {
        	System.out.println(e.getMessage());
        }
    }
	
	private void atualizaTabelaPadrao(File file, TabelaPadrao tabelaTP) throws Exception {

		PreparedStatement stmt = null;
		setForeignKeyConstraintsCheck(false);
		stmt = connection.prepareStatement("delete from " + tabelaTP.getNomeTabela() );
		try{ 
			stmt.execute();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		setForeignKeyConstraintsCheck(true);

		
		/*
		 * Inclui linhas na tabela a partir do XML
		 */
		try {
			SAXParser saxParser;
			saxParser = SAXParserFactory.newInstance().newSAXParser();
			TabelaPadraoXMLHandler tpHandle = new TabelaPadraoXMLHandler(connection);
			saxParser.parse(file, tpHandle);

		} catch (Exception e) {
			System.out.println(e.getMessage());
			return;
		}

		/*
		 * Atualizo a versao no banco de dados
		 */
		try {
			stmt = connection.prepareStatement("select * from TabelaPadrao where NOMETABELA = ? ");
			stmt.setString(1, tabelaTP.getNomeTabela());
			ResultSet rs = stmt.executeQuery();
			if (rs.next()) {
				PreparedStatement stmtB = connection.prepareStatement("update TabelaPadrao " + 
						"set VERSAO = ? " + 
						"where 1=1 " + 
						"and NOMETABELA = ? ");
				stmtB.setInt(1, tabelaTP.getVersao());
				stmtB.setString(2, tabelaTP.getNomeTabela());
				try {
					stmtB.execute();
				} catch (Exception e) {
					System.out.println(e.getMessage());
				}
				stmtB.close();
			} else {
				PreparedStatement stmtB = connection.prepareStatement( "insert into TabelaPadrao " + 
						"( ID, TABELA, NOMEARQUIVO, NOMETABELA, VERSAO, CONDICAO, TOTALREGISTROS ) " + 
						"values( ?, ?, ?, ?, ?, ?, ? ) " );
				stmtB.setInt(1, tabelaTP.getTabela());
				stmtB.setInt(2, tabelaTP.getTabela());
				stmtB.setString(3, tabelaTP.getNomeArquivo());
				stmtB.setString(4, tabelaTP.getNomeTabela());
				stmtB.setInt(5, tabelaTP.getVersao());
				stmtB.setString(6, tabelaTP.getCondicao());
				stmtB.setInt(7, tabelaTP.getTotalRegistros());
				try {
					stmtB.execute();
				} catch (Exception e) {
					System.out.println(e.getMessage());
				}
				stmtB.close();
				
				
				
			}
			rs.close();
			stmt.close();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		
		stmt.close();

//		atualizaTabelaPadrao(tabelaTP);
		
	}
	
//	@SuppressWarnings("unchecked")
//	private void atualizaTabelaPadrao(TabelaPadrao tabPadrao){
//		TabelaPadrao tp = new TabelaPadrao();
//		
//		Query q = em.createNamedQuery("tabelaPadrao.porTabela");
//		q.setParameter("nomeTbl", tabPadrao.getNomeTabela());
//		List<TabelaPadrao> lTabelaPadrao = q.getResultList();
//		if (lTabelaPadrao.size() > 0) {
//			tp = lTabelaPadrao.get(0);
//			tp.setVersao(tabPadrao.getVersao()+1);
//			
//			tp = em.merge(tp);
//		} else {
//			tp = em.merge(tabPadrao);
//		}
//
//	}

	public void setPath(String path) {
		this.path = path;
	}

	public String getPath() {
		return path;
	}

	// public void setMnemonico(String mnemonico) {
	// this.mnemonico = mnemonico;
	// }
	// public String getMnemonico() {
	// return mnemonico;
	// }

	public String getArquivoConfigXML() {
		return arquivoConfigXML;
	}

	public void setArquivoConfigXML(String arquivoConfigXML) {
		this.arquivoConfigXML = arquivoConfigXML;
	}
}